package com.gitee.wsl.concurrent.api.disposable

import kotlinx.atomicfu.atomic
import kotlin.concurrent.Volatile

/**
 * Represents a disposable resource.
 *
 * The following factory functions are available:
 * - `Disposable()`
 * - `Disposable(onDispose: {})`.
 */
interface Disposable : AutoCloseable {

    /**
     * Checks whether this resource is disposed or not
     *
     * @return true if this resource is disposed, false otherwise
     */
    val isDisposed: Boolean

    /**
     * Disposes this resource
     */
    fun dispose()

    override fun close() = dispose()
}


fun <T : Disposable> T.addTo(compositeDisposable: CompositeDisposable): T {
    compositeDisposable.add(this)

    return this
}

internal inline fun Disposable.doIfNotDisposed(dispose: Boolean = false, block: () -> Unit) {
    if (!isDisposed) {
        try {
            block()
        } finally {
            if (dispose) {
                dispose()
            }
        }
    }
}


inline fun Disposable(crossinline onDispose: () -> Unit): Disposable =
    object :  Disposable {
        private val atomicBoolean = atomic(false)

        override val isDisposed: Boolean
            get() = atomicBoolean.value

        override fun dispose() {
            if (atomicBoolean.compareAndSet(false, true)) {
                onDispose()
            }
        }
    }

fun Disposable(): Disposable = SimpleDisposable()

private class SimpleDisposable : Disposable {
    @Volatile
    override var isDisposed: Boolean = false
        private set

    override fun dispose() {
        isDisposed = true
    }
}